﻿using System;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
using System.Xml;

namespace Universe.WCF.Behaviors.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost sh = new ServiceHost(typeof(Service1<int>));
            NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, false);

            NetNamedPipeBinding pipe = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
            pipe.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            pipe.MaxReceivedMessageSize = Int32.MaxValue;

            int idProcess = Process.GetCurrentProcess().Id;
            string uri = "net.pipe://localhost/uesamples/calc/" + idProcess;

            EndpointAddress ea = new EndpointAddress("net.tcp://localhost:54321/Svc1");
            EndpointAddress eaPipe = new EndpointAddress(uri);

            TransparentDeliveryConfiguration tdc = new TransparentDeliveryConfiguration(
                delegate(string action, DeliveryDictionary data)
                    {
                        data.Set<int>("ID", 321);
                        // data.Set<Guid>("ID", Guid.NewGuid());
                    },
                delegate(string action, DeliveryDictionary data)
                    {
                        int id = data.Get<int>("ID");
                        // Console.WriteLine("Transparent value: " + id);
                    });

            ServiceEndpoint ep = sh.AddServiceEndpoint(typeof(IService1<int>), pipe, eaPipe.Uri);
            TransparentDeliveryBehavior transparentDeliveryBehavior = new TransparentDeliveryBehavior(tdc);
            ep.Behaviors.Add(transparentDeliveryBehavior);
            sh.Description.Behaviors.Add(new TrafficBehavior(TrafficStatisticConfiguration.Common));

            // NetDataContractFormat.ApplyTo(sh);

            ServiceDebugBehavior beh = sh.Extensions.Find<ServiceDebugBehavior>();
            sh.Open();

            NetTcpBinding cb = new NetTcpBinding(SecurityMode.None, false);
            NetNamedPipeBinding cb2 = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
            cb2.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            cb2.MaxReceivedMessageSize = Int32.MaxValue;
            ChannelFactory<IService1<int>> cf = new ChannelFactory<IService1<int>>(cb2);
            cf.Endpoint.Behaviors.Add(new TrafficBehavior(TrafficStatisticConfiguration.Common));

            TransparentDeliveryBehavior td2 = new TransparentDeliveryBehavior(tdc);
            cf.Endpoint.Behaviors.Add(td2);
            // NetDataContractFormat.ApplyTo(cf);

            TrafficStatistic clientTraffic = new TrafficStatistic();
            TrafficBehavior.ApplyTo(cf,
                clientTraffic.Merge);

            IService1<int> proxy = cf.CreateChannel(new EndpointAddress(eaPipe.Uri));

            TrafficDefaultInfo.BindToCommon();
            
            proxy.GetData(1, typeof (String));
            proxy.GetData(new CompositeType() {BoolValue = true, StringValue = new string('q', 1000000)});

            try
            {
                proxy.ThrowException("welcome back");
            }
            catch(FaultException<ExceptionDetail> ex)
            {
                Console.WriteLine("Response to ThrowException: {0}: {1}", ex.GetType(), ex.Message);
                cf.Abort();
            }
            catch(Exception ex)
            {
                Console.WriteLine("Response to ThrowException: {0}: {1}", ex.GetType(), ex.Message);
                Console.WriteLine(ex);
                cf.Abort();
            }

            TrafficDefaultInfoWriter.Flush("my_traffic.log");


            Console.WriteLine("CLIENT" + Environment.NewLine + clientTraffic.ToPlainReport());

            Thread thread = new Thread(
                delegate()
                    {
                        cf = new ChannelFactory<IService1<int>>(cb2);
                        TransparentDeliveryConfiguration tdc2 = new TransparentDeliveryConfiguration(
                            delegate(string action, DeliveryDictionary data)
                                {
                                    data.Set("ID", 555);
                                }, 
                                delegate {  });

                        cf.Endpoint.Behaviors.Add(new TransparentDeliveryBehavior(tdc2));
                        cf.Endpoint.Behaviors.Add(new TrafficBehavior());

                        cf.Open();
                        proxy = cf.CreateChannel(new EndpointAddress(uri));
                        while(true)
                        {
                            proxy.GetData(new CompositeType() {BoolValue = true, StringValue = "hi"});
                            Thread.Sleep(99);
                        }

                    });

            thread.IsBackground = true;
            thread.Start();

            Console.ReadLine();
            cf.Close();
            sh.Close();
        }
    }
}